package com.pandi.springboot_jwt.controller;

import com.pandi.springboot_jwt.component.TokenParams;

import com.pandi.springboot_jwt.dto.request.StaffLoginReqFrom;
import com.pandi.springboot_jwt.entity.Staff;
import com.pandi.springboot_jwt.result.Result;
import com.pandi.springboot_jwt.service.ILoginService;

import com.pandi.springboot_jwt.utils.JWTUtils;
import com.pandi.springboot_jwt.utils.RedisUtils;
import com.pandi.springboot_jwt.utils.TokenUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;

import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.HashMap;

/**
 * @author pandi
 * @create 2020-12-31 11:30
 */

@RestController
@CrossOrigin
@Api(value = "LoginController", tags = {"登录API"})
public class LoginController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    private ILoginService loginService;

    @Autowired
    private TokenParams tokenParams;

    @Autowired
    private RedisUtils redisUtil;

    /**
     *
     * 单系统集群版方案->JWT生产方案
     */
    @ApiOperation(value = "登录接口")
    @ApiImplicitParam(name="staffLoginReqForm", value = "登录实体", required = true, dataType = "StaffLoginReqForm")
    @PostMapping("login1")
    public Result login(HttpServletRequest request, HttpServletResponse response,
                        @Validated @RequestBody StaffLoginReqFrom staffLoginReqFrom){

        Result result = loginService.Login(staffLoginReqFrom.getAccount(), staffLoginReqFrom.getPassword());
        Staff staff = (Staff) result.getData();

        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("account",staff.getAccount());
        hashMap.put("staff_id",staff.getId());

        String token = JWTUtils.getToken(hashMap);

        response.setHeader("token", token);
        result.setData(token);
        return result;
    }



    /**
     *
     * 单系统集群版方案-> 自定义生成key存入redis方案
     */
    @ApiOperation(value = "登录接口")
    @ApiImplicitParam(name="staffLoginReqForm", value = "登录实体", required = true, dataType = "StaffLoginReqForm")
    @PostMapping("login2")
    public Result login2(HttpServletRequest request, HttpServletResponse response,
                         @Validated @RequestBody StaffLoginReqFrom staffLoginReqFrom){

        Result result = loginService.Login(staffLoginReqFrom.getAccount(), staffLoginReqFrom.getPassword());
        Staff staff = (Staff) result.getData();

        String token = TokenUtil.getToken(staff.getId(), staff.getAccount(), staff.getUsername());
        boolean isSuccess = this.token2Redis(staff.getId(), token, tokenParams.getExpireTime());

        if(isSuccess){
            response.setHeader("authorization", token);
            response.setHeader("id", staff.getId());
            logger.info("Success to login in the LoginController!");
        }else {
            result.setData("");
            logger.info("Failed to login in the LoginController! Cause redis verify or insert failed!");
        }
        return result;

    }

    private boolean token2Redis(String id, String token, int expireTime){
        logger.info("Start to save token in redis!");

        boolean isLogin = false;
        if(StringUtils.isNotEmpty(id)){
            String lastToken = (String) redisUtil.get(id);
            if(StringUtils.isNotEmpty(lastToken)){
                redisUtil.del(id);
            }
            boolean success = redisUtil.set(id, token, expireTime);
            if(success){
                isLogin = true;
            }
        }
        return isLogin;
    }


    /**
     *
     * 单系统集群版方案-> shiro
     */
    @ApiOperation(value = "登录接口")
    @ApiImplicitParam(name="staffLoginReqForm", value = "登录实体", required = true, dataType = "StaffLoginReqForm")
    @PostMapping("login3")
    public Result login3(HttpServletRequest request, HttpServletResponse response,
                         @Validated @RequestBody StaffLoginReqFrom staffLoginReqFrom){

        Result result = new Result();
        //获取subject主体
        Subject subject = SecurityUtils.getSubject();

        try {
            subject.login(new UsernamePasswordToken(staffLoginReqFrom.getAccount(),staffLoginReqFrom.getPassword()));
            result.setData("认证通过");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名错误");
            result.setData("用户名错误");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误");
            result.setData("密码错误");
        }

        return result;
    }

    @PostMapping("logout")
    public Result logout(){
        Result result = new Result();
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        result.setData("退出成功");
        return result;
    }




}
